<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  
  <title>Redis入门 | conor_hua</title>
  <meta name="description" content="辉夜大小姐想让我写博客。" />
  <meta name="keywords" content="Java,Sakura,spring" />
  
    <link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/favicon00.ico">
  
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <!--自定义看板娘-->
  <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
  <script src="/live2d-widget/autoload.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"/>

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/googlefont.css" media="all">
<!--  <link rel="dns-prefetch" href="//cdn.jsdelivr.net">-->
  <link rel="stylesheet" id="saukra_css-css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/style.css" type="text/css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/lib.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/font.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/insight.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/jquery.fancybox.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/zoom.css" media="all">
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/sharejs.css">
  <link rel="stylesheet" href="/css/tags.css" media="all">
  <!--   <link rel="stylesheet" id="saukra_css-css" href="https://2heng.xin/wp-content/cache/autoptimize/css/autoptimize_ad42a61f4c7d4bdd9f91afcff6b5dda5.css
" type="text/css" media="all"> -->
  <script>
  /*Initial Variables*/
  var mashiro_option = new Object();
  var mashiro_global = new Object();
  mashiro_option.NProgressON = true;
  /* 
   * 邮箱信息之类的东西可以填在这里，这些js变量基本都作用于sakura-app.js
   * 这样的设置仅是为了方便在基于PHP开发的主题中设置js变量，既然移植到了Node上，我想或许可以精简这一逻辑吧
   */
  mashiro_option.email_domain = "";
  mashiro_option.email_name = "";
  mashiro_option.cookie_version_control = "";
  mashiro_option.qzone_autocomplete = false;
  mashiro_option.site_name = "Conor_hua";
  mashiro_option.author_name = "";
  mashiro_option.site_url = "https://conor_hua.gitee.io";
  mashiro_option.v_appId = "GyC3NzMvd0hT9Yyd2hYIC0MN-gzGzoHsz";
  mashiro_option.v_appKey = "mgOpfzbkHYqU92CV4IDlAUHQ";
  mashiro_option.mathjax = "0";
  mashiro_option.qq_api_url = "https://api.mashiro.top/qqinfo/"; 
  mashiro_option.qq_avatar_api_url = "https://api.mashiro.top/qqinfo/";

  // mashiro_option.jsdelivr_css_src = "https://cdn.jsdelivr.net/gh/moezx/cdn@3.4.5/css/lib.min.css";
  // mashiro_option.float_player_on = true;

  /*End of Initial Variables*/
  </script>
  <script type="text/javascript">
  var bg = "https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/6f005cbc1865ff1b706aba57347988ab.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/ox83gp.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/a5fa4f9db760f58fc48f03d66b4967f7.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/zm3vey.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/b3e8dae89b950b940dc0edd1e8cc0566.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/j58y6y.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/4217z9.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/j5zg2p.jpg".split(",");
  var bgindex = Math.floor(Math.random()*bg.length);
  if (!!window.ActiveXObject || "ActiveXObject" in window) { //is IE?
    alert('朋友，IE浏览器未适配哦~');
  }
  </script>
  <style type="text/css">
  .hljs-ln{border-collapse:collapse}.hljs-ln td{padding:0}.hljs-ln-n:before{content:attr(data-line-number)}
  </style>
  <style type="text/css">.site-top .lower nav{display:block !important;}.author-profile i,.post-like a,.post-share .show-share,.sub-text,.we-info a,span.sitename,.post-more i:hover,#pagination a:hover,.post-content a:hover,.float-content i:hover{color:#FE9600}.feature i,.download,.navigator i:hover,.links ul li:before,.ar-time i,span.ar-circle,.object,.comment .comment-reply-link,.siren-checkbox-radio:checked + .siren-checkbox-radioInput:after{background:#FE9600}::-webkit-scrollbar-thumb{background:#FE9600}.download,.navigator i:hover,.link-title,.links ul li:hover,#pagination a:hover,.comment-respond input[type='submit']:hover{border-color:#FE9600}.entry-content a:hover,.site-info a:hover,.comment h4 a,#comments-navi a.prev,#comments-navi a.next,.comment h4 a:hover,.site-top ul li a:hover,.entry-title a:hover,#archives-temp h3,span.page-numbers.current,.sorry li a:hover,.site-title a:hover,i.iconfont.js-toggle-search.iconsearch:hover,.comment-respond input[type='submit']:hover{color:#FE9600}.comments .comments-main{display:block !important;}.comments .comments-hidden{display:none !important;}background-position:center center;background-attachment:inherit;}
  </style>
<script src="https://cdn.jsdelivr.net/gh/conorhua/asset/js/hititle.js"></script>
<meta name="generator" content="Hexo 4.2.1"></head>

<body class="page-template page-template-user page-template-page-analytics page-template-userpage-analytics-php page page-id-1297 chinese-font serif isWebKit">
  <div class="scrollbar" id="bar">
  </div>
  <a href="#" class="cd-top faa-float animated"></a>
  <section id="main-container">
    <div class="headertop filter-dot">
  <div id="banner_wave_1"></div>
  <div id="banner_wave_2"></div>
  <figure id="centerbg" class="centerbg">
    <div class="focusinfo no-select">
      <div class="header-tou">
        <a href="https://conor_hua.gitee.io" target="_blank" rel="noopener">
          <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
        </a>
      </div>
      <div class="header-info">
        <p id="jinrishici-sentence">正在加载今日诗词....</p>
        <script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>
        <div class="top-social_v2">
          <li id="bg-pre">
            <img class="flipx" src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
          
          
          
          <li>
            <a href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&amp;email=1_bi5eLm4_Tj4uGXpqb5tLi6" target="_blank" class="social-github" title="email">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/email.png">
            </a>
          </li>
          
          
          
          <li class="wechat">
            <a href="/#">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/wechat.png">
            </a>
            <div class="wechatInner">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/1.jpg">
            </div>
          </li>
          
          
          
          <li id="bg-next">
            <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
        </div>
      </div>
    </div>
  </figure>
  
  <div id="video-container" style="display: none;">
    <video style="object-fit: fill" id="bgvideo" class="video" video-name="" src="" width="auto" preload="auto">
    </video>
    <div id="video-btn" class="loadvideo videolive">
    </div>
    <div id="video-add">
    </div>
    <div class="video-stu">
    </div>
  </div>
  
  <div class="headertop-down faa-float animated" onclick="headertop_down()">
    <span>
      <i class="fa fa-chevron-down" aria-hidden="true">
      </i>
    </span>
  </div>
</div>
    <div id="page" class="site wrapper">
      <header class="site-header no-select gizle sabit" role="banner">
 
  <div class="site-top">
    <div class="site-branding">
      <span class="site-title">
        <span class="logolink moe-mashiro">
          <a href="/">
            <span class="sakurasono">Conor_hua</span>
            <span class="shironeko"></span>
          </a>
        </span>
      </span>
    </div>
    <div class="searchbox search-form-submit">
      <i class="iconfont js-toggle-search iconsearch icon-search">
      </i>
    </div>
    <div id="show-nav" class="showNav mobile-fit">
      <div class="line line1">
      </div>
      <div class="line line2">
      </div>
      <div class="line line3">
      </div>
    </div>
    <div class="lower-cantiner">
      <div class="lower">
        <nav class="mobile-fit-control hide">
          <ul id="menu-new" class="menu">
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
                    首页
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
                    归档
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/%E6%8A%80%E6%9C%AF/">
                          <i class="fa fa-code" aria-hidden="true"></i>
                          技术
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/%E5%B9%B2%E8%B4%A7/">
                          <i class="fa fa-plug" aria-hidden="true"></i>
                          干货
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="javascript:;">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
                    清单
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/bangumis/">
                          <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                          番剧
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/%E6%94%B6%E8%97%8F/">
                          <i class="fa fa-star" aria-hidden="true"></i>
                          收藏
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/tags/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-tags" aria-hidden="true"></i>
                    标签
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="javascript:;">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
                    关于
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/about/">
                          <i class="fa fa-meetup" aria-hidden="true"></i>
                          我？
                        </a>
                      </li>
                    
                      <li>
                        <a href="/theme-sakura/">
                          <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                          主题
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/links/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
                    友人帐
                  </span>
                </a>
                
              </li>
            
          </ul>
        </nav>
      </div>
    </div>
  </div>
</header>

      <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/sharejs.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/tocbot.css">
<div class="pattern-center-blank"></div>

  <div class="pattern-center single-center">
    <!-- 有配图默认渲染第一张 -->
    <div class="pattern-attachment-img">
        <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-q2lm9l.jpg" class="lazyload" onerror="imgError(this,3)" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;">
      </div>
    <header class="pattern-header single-header">
      <h1 class="entry-title">
      Redis入门</h1>
      <p class="entry-census">
        <span>
          <a href="">
            <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
          </a>
        </span>
        <span>
          <a href="">Conor_hua</a>
        </span>
        <span class="bull">
        ·</span>
        2021-8-11
        
      
        ·<span id="readcount"></span>次阅读
      
      </p>
    </header>
  </div>

<div id="content" class="site-content">
  <div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
      <article id="post-1" class="post-1 post type-post status-publish format-standard has-post-thumbnail hentry category-uncategorized">
        <div class="toc"></div>
        <!--<div class="toc-entry-content"> <!-- 套嵌目录使用（主要为了支援评论）-->
        
        <div class="entry-content">
          <p>本博客是NoSQL的学习笔记。主要是记录方便日后回档。</p>
<p><a href="https://baike.baidu.com/item/NoSQL/8828247?fr=aladdin" target="_blank" rel="noopener">NoSQL-百科</a></p>
<p><a href="https://redis.io/" target="_blank" rel="noopener">Redis</a></p>
<p><a href="http://www.redis.cn/" target="_blank" rel="noopener">Redis中文</a></p>
<p><a href="https://www.cnblogs.com/chenliangcl/p/7240350.html" target="_blank" rel="noopener">Redis持久化机制</a></p>
<p><a href="https://www.bilibili.com/video/BV1XV411o7xP?p=85" target="_blank" rel="noopener">Redis教程，入门到实战</a></p>
<h2 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h2><p>​    NoSQL ( Not Only SQL )，泛指非关系型的数据库。高性能，高扩展性，不遵循SQL标准，不保证ACID特性。</p>
<p>特点：</p>
<ul>
<li>易扩展<ul>
<li>NoSQL数据库去掉关系数据库的关系型特性，非常容易扩展</li>
</ul>
</li>
<li>大数据量，高性能<ul>
<li>NoSQL数据库具有非常高的读写性能，尤其在大数据量下，同样表现优秀。</li>
</ul>
</li>
<li>灵活的数据模型<ul>
<li>NoSQL无须事先为要存储的数据建立字段，随时可以存储自定义的数据格式。</li>
</ul>
</li>
<li>高可用<ul>
<li>NoSQL在不太影响性能的情况，就可以方便地实现高可用的架构。比如Cassandra、HBase模型，通过复制模型也能实现高可用。</li>
</ul>
</li>
</ul>
<p>NoSQL适用于高并发读写，海量数据读写，对数据高可扩展性要求。</p>
<p>分类:</p>
<p><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/1.png" alt="分类"></p>
<h2 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h2><p>​    Redis (Remote Dictionary Server )，即远程字典服务，使用ANSI C语言编写， 是一个开源的key-value的NoSQL数据库。</p>
<p>因为 redis 是完全基于内存操作的，通常情况下CPU不会是redis的瓶颈，redis 的瓶颈最有可能是磁盘I/O，机器内存的大小或者网络带宽。</p>
<p>既然CPU不会成为瓶颈，那就顺理成章地采用单线程的方案了，因为如果使用多线程的话会更复杂，同时需要引入上下文切换、加锁等等，会带来额外的性能消耗。</p>
<p>而随着近些年互联网的不断发展，大家对于缓存的性能要求也越来越高了，因此 redis 也开始在逐渐往多线程方向发展。</p>
<p>最近的 6.0 版本就对核心流程引入了多线程，主要用于解决 redis 在网络 I/O 上的性能瓶颈。而对于核心的命令执行阶段，目前还是单线程的。</p>
<h3 id="5大数据类型及其常见命令"><a href="#5大数据类型及其常见命令" class="headerlink" title="5大数据类型及其常见命令"></a>5大数据类型及其常见命令</h3><p>redis以key-value的形式存放数据，常用的数据类型有string ，hashes ，lists，sets，sorted sets，先看看一些常见操作：</p>
<p>redis-cli启动redis客户端</p>
<p>select命令切换数据库 默认有16个数据库0~15，</p>
<p>dbsize查看当前数据库key数量</p>
<p>flushdb清空当前库！</p>
<p>flushall清空all库！！</p>
<p>keys *命令查看当前存在的key</p>
<p>exists命令查看是否存在key</p>
<p>del命令删除key</p>
<p>unlink命令 非阻塞删除 (空闲时才真正删除数据)</p>
<p>expire命令设置key过期时间</p>
<p>ttl返回给定 key 的剩余生存时间 -1表示永不过期， -2表示已过期</p>
<pre><code class="linux"> set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [G
[root@aliyun ~]# redis-cli
set命令新增key-value
127.0.0.1:6379&gt; set k1 conor
OK
127.0.0.1:6379&gt; set k2 mary
OK
127.0.0.1:6379&gt; set k3 lili
OK
127.0.0.1:6379&gt; set k3 mimi
OK
keys *命令查看当前存在的key
127.0.0.1:6379&gt; keys *
1) &quot;k2&quot;
2) &quot;k1&quot;
3) &quot;k3&quot;
exists命令查看是否存在key
127.0.0.1:6379&gt; exists k1
(integer) 1
127.0.0.1:6379&gt; exists k4
(integer) 0
del命令删除key
127.0.0.1:6379&gt; del k2
(integer) 1
unlink命令 非阻塞删除 (空闲时才真正删除数据)
127.0.0.1:6379&gt; unlink k3
(integer) 1
expire命令设置key过期时间
127.0.0.1:6379&gt; expire k1 20
(integer) 1
ttl返回给定 key 的剩余生存时间 -1表示永不过期， -2表示已过期
127.0.0.1:6379&gt; ttl k1
(integer) 13
127.0.0.1:6379&gt; ttl k1
(integer) 1
127.0.0.1:6379&gt; ttl k1
(integer) -2
</code></pre>
<h4 id="String"><a href="#String" class="headerlink" title="String"></a>String</h4><p>​    二进制安全的字符串，故可存放任何种类的字符串，但不可大于512M。底层是动态字符串，长度小于1M时成倍扩容，大于1M时每次扩容1M。</p>
<p>基本命令:</p>
<p>set 新增key-value</p>
<p>get获取key的值</p>
<p>append在末尾追加，返回总长度</p>
<p>strlen返回string的长度</p>
<p>setnx只有在key不存在时才能新增，不能进行覆盖替换。</p>
<pre><code class="linux">set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [G
127.0.0.1:6379&gt; set k1 v1
OK
127.0.0.1:6379&gt; set k2 v2
OK
127.0.0.1:6379&gt; set k3 v3
OK
------------------------------
get key
127.0.0.1:6379&gt; get k1
&quot;v1&quot;
------------------------------
append key value
127.0.0.1:6379&gt; append k1 appendString
(integer) 14
127.0.0.1:6379&gt; get k1
&quot;v1appendString&quot; 
------------------------------
strlen key
127.0.0.1:6379&gt; strlen k1
(integer) 14
------------------------------
setnx key value
127.0.0.1:6379&gt; setnx k1 aaaa
(integer) 0
127.0.0.1:6379&gt; get k1
&quot;v1appendString&quot;</code></pre>
<p>incr 将数值类型+1,只能对数值类型操作</p>
<p>decr将数值类型-1,只能对数值类型操作</p>
<p>incrby自定义+多少 incrby &lt; key&gt; 10</p>
<p>decrby自定义-多少</p>
<pre><code class="linux">127.0.0.1:6379&gt; set k4 100
OK
127.0.0.1:6379&gt; get k4
&quot;100&quot;
127.0.0.1:6379&gt; incr k4
(integer) 101
127.0.0.1:6379&gt; incrby k4 100
(integer) 201
127.0.0.1:6379&gt; decr k4
(integer) 200
127.0.0.1:6379&gt; decrby k4 100
(integer) 100
127.0.0.1:6379&gt; incr k1
(error) ERR value is not an integer or out of range</code></pre>
<p>mset一次设置多个key-value</p>
<p>mget一次取多个值</p>
<p>msetnx一次设置多个key-value，不替换，全部成功才执行。</p>
<p>setrange设置key的范围</p>
<p>getrange获取key的范围</p>
<p>getset设置新的值并获取旧的值</p>
<pre><code class="linux"> mset key value [key value ...]

127.0.0.1:6379&gt; mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379&gt; keys *
1) &quot;k2&quot;
2) &quot;k1&quot;
3) &quot;k3&quot;
 ------------------------------
 msetnx key value [key value ...] 全部成功才执行
127.0.0.1:6379&gt; msetnx k3 v3 k4 v4
(integer) 0
127.0.0.1:6379&gt; keys *
1) &quot;k2&quot;
2) &quot;k1&quot;
3) &quot;k3&quot;
 ------------------------------
  mget key [key ...]
127.0.0.1:6379&gt; mget k1 k2 k3
1) &quot;v1&quot;
2) &quot;v2&quot;
3) &quot;v3&quot;
 ------------------------------
 setrange key offset value
 getrange key start end
  getset key value
127.0.0.1:6379&gt; setrange k1 1 aaa
(integer) 4
127.0.0.1:6379&gt; get k1
&quot;vaaa&quot;
127.0.0.1:6379&gt; getrange k1 1 3
&quot;aaa&quot;
127.0.0.1:6379&gt; getset k1 v1
&quot;vaaa&quot;
127.0.0.1:6379&gt; get k1
&quot;v1&quot;</code></pre>
<h4 id="List"><a href="#List" class="headerlink" title="List"></a>List</h4><p>​    list可以一个key对应多个value，按照插入顺序排序。底层数据结构是用链表+zipList组成quickList，可以简单的看成是双向链表。</p>
<p>常用命令：</p>
<p>lpush/rpush：&lt; key&gt; &lt; values1&gt;&lt; values2&gt;…从左边/右边插入值</p>
<p>lpop/rpop &lt; key&gt;从左边/右边移除一个值</p>
<p>rpoplpush &lt; key1&gt;&lt; key2&gt; 从key1右边移除一个值到key2左边</p>
<p>lrange &lt; key&gt;&lt; start&gt; &lt; end&gt; 0  -1表示取全部</p>
<p>lindex &lt; key&gt;&lt; index&gt;按照索引下标获取元素</p>
<p>llen&lt; key&gt;获取key的列表长度</p>
<p>linsert&lt; key&gt; before &lt; value&gt; &lt; newvalue&gt;在value左边插入一个新值</p>
<p>lrem &lt; key&gt; &lt; n&gt; &lt; value&gt; 从左边开始 删除n个value</p>
<p>lset&lt; key&gt;&lt; index&gt;&lt; value&gt; 替换索引为index的值</p>
<pre><code class="linux">127.0.0.1:6379&gt; lpush k1 v11 v12 v13
(integer) 3
127.0.0.1:6379&gt; lrange k1 0 -1
1) &quot;v13&quot;
2) &quot;v12&quot;
3) &quot;v11&quot;
127.0.0.1:6379&gt; rpush k2 v21 v22 v23
(integer) 3
127.0.0.1:6379&gt; lrange k2 0 -1
1) &quot;v21&quot;
2) &quot;v22&quot;
3) &quot;v23&quot;
127.0.0.1:6379&gt; lpop k1
&quot;v13&quot;
127.0.0.1:6379&gt; lrange k1 0 -1
1) &quot;v12&quot;
2) &quot;v11&quot;
127.0.0.1:6379&gt; lindex k1 0
&quot;v12&quot;
127.0.0.1:6379&gt; rpoplpush k2 k1
&quot;v23&quot;
127.0.0.1:6379&gt; lrange k1 0 -1
1) &quot;v23&quot;
2) &quot;v12&quot;
3) &quot;v11&quot;
127.0.0.1:6379&gt; linsert k1 before v12 newvalue
(integer) 4
127.0.0.1:6379&gt; lset k1 1 v11
OK
127.0.0.1:6379&gt; lrange k1 0 -1
1) &quot;v23&quot;
2) &quot;v11&quot;
3) &quot;v12&quot;
4) &quot;v11&quot;
127.0.0.1:6379&gt; lrem k1 1 v11
(integer) 1
127.0.0.1:6379&gt; lrange k1 0 -1
1) &quot;v23&quot;
2) &quot;v12&quot;
3) &quot;v11&quot;</code></pre>
<h4 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h4><p> set是无序集合，元素唯一，底层通过hash表实现，添加，删除，查找的复杂度都是 O(1)。</p>
<p>常用命令：</p>
<p>sadd &lt; key&gt; &lt; value1&gt; &lt; value2&gt;..插入到set中</p>
<p>smembers &lt; key&gt;取set里所有值</p>
<p>sismember &lt; key&gt; &lt; value&gt; 判断value是否存在</p>
<p>scard&lt; key&gt;返回元素个数</p>
<p>srem &lt; key&gt; &lt; value1&gt; &lt; value2&gt;..移除元素</p>
<p>spop&lt; key&gt; 随机移除值</p>
<p>srandmember&lt; key&gt;&lt; n&gt;随机取出n个值</p>
<p>smove &lt; key1&gt;&lt; key2&gt;把key1中的一个值移动到key2</p>
<p>sinter&lt; key1&gt;&lt; key2&gt; 返回交集</p>
<p>sunion&lt; key1&gt;&lt; key2&gt; 并集</p>
<p>sdiff&lt; key1&gt;&lt; key2&gt;差集</p>
<pre><code class="linux">127.0.0.1:6379&gt; sadd k1 v1 v2 v3 v4 v3
(integer) 4
127.0.0.1:6379&gt; smembers k1
1) &quot;v1&quot;
2) &quot;v4&quot;
3) &quot;v2&quot;
4) &quot;v3&quot;
127.0.0.1:6379&gt; sismember k1 v1
(integer) 1
127.0.0.1:6379&gt; sismember k1 v5
(integer) 0
127.0.0.1:6379&gt; scard k1
(integer) 4
127.0.0.1:6379&gt; srem k1 v4
(integer) 1
127.0.0.1:6379&gt; smembers k1
1) &quot;v1&quot;
2) &quot;v3&quot;
3) &quot;v2&quot;
127.0.0.1:6379&gt; spop k1
&quot;v1&quot;
127.0.0.1:6379&gt; smembers k1
1) &quot;v3&quot;
2) &quot;v2&quot;
127.0.0.1:6379&gt; srandmember k1 1
1) &quot;v2&quot;

127.0.0.1:6379&gt; sadd k1 v1 v2 v3
(integer) 1
127.0.0.1:6379&gt; sadd k2 v4 v2 v3
(integer) 3
127.0.0.1:6379&gt; sinter k1 k2
1) &quot;v3&quot;
2) &quot;v2&quot;
127.0.0.1:6379&gt; sunion k1 k2
1) &quot;v1&quot;
2) &quot;v4&quot;
3) &quot;v2&quot;
4) &quot;v3&quot;
127.0.0.1:6379&gt; sdiff k1 k2
1) &quot;v1&quot;</code></pre>
<h4 id="Hash"><a href="#Hash" class="headerlink" title="Hash"></a>Hash</h4><p>​    hash是一个field-value的映射表，类似于map&lt;String，Object&gt;</p>
<p>底层数据结构是ziplist和hashtable，数据少且短时用ziplist，否则用hashtable。</p>
<p>常用命令：</p>
<p>hset &lt; key&gt; &lt; field&gt;&lt; value&gt; 添加</p>
<p>hsetnx&lt; key&gt; &lt; field&gt;&lt; value&gt;  field不存在时才可以添加</p>
<p>hget &lt; key&gt; &lt; field&gt; 取出</p>
<p>hgetall &lt; key&gt;获取所有field - value</p>
<p>hdel &lt; key&gt; &lt; field1&gt; &lt; field2&gt;…删除field</p>
<p>hexists &lt; key&gt; &lt; field&gt; 是否存在</p>
<p>hlen &lt; key&gt;长度</p>
<p>hkeys &lt; key&gt; 取所有field</p>
<p>hvals&lt; key&gt; 取所有value</p>
<p>hincrby &lt; key&gt;&lt; field&gt;&lt; increment&gt;为field的value增量</p>
<pre><code class="linux">127.0.0.1:6379&gt; hset user:001 name xiaoming age 18
(integer) 2
127.0.0.1:6379&gt; hgetall user:001
1) &quot;name&quot;
2) &quot;xiaoming&quot;
3) &quot;age&quot;
4) &quot;18&quot;
127.0.0.1:6379&gt; hkeys user:001
1) &quot;name&quot;
2) &quot;age&quot;
127.0.0.1:6379&gt; hvals user:001
1) &quot;xiaoming&quot;
2) &quot;18&quot;
127.0.0.1:6379&gt; hincrby user:001 age 10
(integer) 28
127.0.0.1:6379&gt; hget user:001 age
&quot;28&quot;
127.0.0.1:6379&gt; hdel user:001 age
(integer) 1
127.0.0.1:6379&gt; hgetall user:001
1) &quot;name&quot;
2) &quot;xiaoming&quot;</code></pre>
<h4 id="zset-sortedSet"><a href="#zset-sortedSet" class="headerlink" title="zset(sortedSet)"></a>zset(sortedSet)</h4><p>sortedSet是有序的唯一的集合，关联一个double型的score进行从小到大排序。数据结构是hash表来实现元素唯一，用跳跃表来实现排序，可以简单的看成是map&lt;String，Double&gt;。</p>
<p>常用命令：</p>
<p>zadd &lt; key&gt;&lt; score1&gt;&lt; value1&gt;&lt; score2&gt;&lt; value2&gt;..添加元素及其score</p>
<p>zrange&lt; key&gt;&lt; start&gt;&lt; end&gt;[withscores]返回下标start end之间的元素</p>
<p>zrangebyscore &lt; key&gt; &lt; min&gt; &lt; max&gt;返回score范围的元素</p>
<p>zrevrangebyscore 同上，改为大到小排序</p>
<p>zincrby &lt; key&gt; &lt; increment&gt;&lt; value&gt;为value增量</p>
<p>zrem&lt; key&gt; &lt; value&gt;删除</p>
<p>zcount&lt; key&gt; &lt; min&gt; &lt; max&gt;统计范围内个数</p>
<p>zrank &lt; key&gt; &lt; value&gt; 返回value的排名</p>
<pre><code class="linux">127.0.0.1:6379&gt; zadd k1 500 java 1000 php 600 go 400 c++
(integer) 4
127.0.0.1:6379&gt; zrange k1 0 -1
1) &quot;c++&quot;
2) &quot;java&quot;
3) &quot;go&quot;
4) &quot;php&quot;
127.0.0.1:6379&gt; zrange k1 0 -1 withscores
1) &quot;c++&quot;
2) &quot;400&quot;
3) &quot;java&quot;
4) &quot;500&quot;
5) &quot;go&quot;
6) &quot;600&quot;
7) &quot;php&quot;
8) &quot;1000&quot;
127.0.0.1:6379&gt; zrangebyscore k1 400 600
1) &quot;c++&quot;
2) &quot;java&quot;
3) &quot;go&quot;
127.0.0.1:6379&gt; zrevrangebyscore k1 600 400
1) &quot;go&quot;
2) &quot;java&quot;
3) &quot;c++&quot;</code></pre>
<h4 id="高级的4种："><a href="#高级的4种：" class="headerlink" title="高级的4种："></a>高级的4种：</h4><ul>
<li>HyperLogLog：通常用于基数统计。使用少量固定大小的内存，来统计集合中唯一元素的数量。统计结果不是精确值，而是一个带有0.81%标准差（standard error）的近似值。所以，HyperLogLog适用于一些对于统计结果精确度要求不是特别高的场景，例如网站的UV统计。</li>
<li>Geo：redis 3.2 版本的新特性。可以将用户给定的地理位置信息储存起来， 并对这些信息进行操作：获取2个位置的距离、根据给定地理位置坐标获取指定范围内的地理位置集合。</li>
<li>Bitmap：位图。</li>
<li>Stream：主要用于消息队列，类似于 kafka，可以认为是 pub/sub 的改进版。提供了消息的持久化和主备复制功能，可以让任何客户端访问任何时刻的数据，并且能记住每一个客户端的访问位置，还能保证消息不丢失。</li>
</ul>
<h2 id="Jedis"><a href="#Jedis" class="headerlink" title="Jedis"></a>Jedis</h2><p>在Java中使用redis需要jedis的支持，就像使用mysql使用jdbc那样子。</p>
<p>引入jedis依赖</p>
<pre><code class="xml">&lt;!-- https://mvnrepository.com/artifact/redis.clients/jedis --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;redis.clients&lt;/groupId&gt;
            &lt;artifactId&gt;jedis&lt;/artifactId&gt;
            &lt;version&gt;3.3.0&lt;/version&gt;
        &lt;/dependency&gt;</code></pre>
<p>创建测试类</p>
<pre><code class="java">Jedis jedis=new Jedis(&quot;IP地址&quot;,6379);
        jedis.auth(&quot;password&quot;);
        String value=jedis.ping();
        System.out.println(value);
        jedis.clone();
//输出pong连接成功</code></pre>
<p>注意:使用阿里云服务器需要设置安全组放行redis的端口，默认端口为6379。务必设置redis的密码，防止阿里云服务器被入侵。</p>
<p>jedis的方法基本与redis的命令一一对应。</p>
<p>如list的简单操作：</p>
<pre><code class="java">@Test
    public void demo01(){
        Jedis jedis=new Jedis(&quot;IP地址&quot;,6379);
        jedis.auth(&quot;password&quot;);

        jedis.lpush(&quot;key1&quot;,&quot;v1&quot;,&quot;v2&quot;,&quot;v3&quot;);
        List&lt;String&gt; key1 = jedis.lrange(&quot;key1&quot;, 0, -1);
        for (String s : key1) {
            System.out.println(s);
        }
        jedis.clone();
    }
//输出v3 v2 v1</code></pre>
<h2 id="Spring-Boot集成redis"><a href="#Spring-Boot集成redis" class="headerlink" title="Spring Boot集成redis"></a>Spring Boot集成redis</h2><p>引入依赖</p>
<pre><code class="xml">&lt;!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
            &lt;version&gt;2.5.5&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
            &lt;artifactId&gt;commons-pool2&lt;/artifactId&gt;
            &lt;version&gt;2.11.1&lt;/version&gt;
        &lt;/dependency&gt;</code></pre>
<p>配置redis一些参数;</p>
<pre><code class="yml">spring:
  redis:
    host: ip地址
    port: 6379
    database: 0
    password: &#39;password&#39;
    lettuce:
      pool:
        max-active: 20
        max-wait: -1
        max-idle: 5
        min-idle: 0</code></pre>
<p>一个简单的测试类:</p>
<pre><code class="java">/**
 * @author Conor
 */
@RestController
@RequestMapping(&quot;/redisTest&quot;)
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping
    public Object test(){
        redisTemplate.opsForValue().set(&quot;key&quot;,&quot;value&quot;);
        return redisTemplate.opsForValue().get(&quot;key&quot;);
    }

}</code></pre>
<p>访问/redisTest</p>
<p><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/response.png" alt="response"></p>
<h2 id="Redis事务"><a href="#Redis事务" class="headerlink" title="Redis事务"></a>Redis事务</h2><p>​    Redis事务是一个单独的隔离操作: 事务中的所有命令都会被序列化，按顺序地执行。事务在执行的过程中，不会被其他客户端送来的命令请求所打断。</p>
<p>​    Redis事务的主要作用是串联多个命令防止别的命令插队。</p>
<h3 id="三个特性："><a href="#三个特性：" class="headerlink" title="三个特性："></a>三个特性：</h3><p>Redis事务与MySQL的事务没有什么联系，Redis事务有三个基本特征</p>
<ul>
<li>单独的隔离操作：事务中的所有命令都会序列化，按顺序执行。</li>
<li>没有隔离级别：事务提交之前队列中所有命令都不会被执行。</li>
<li>不保证原子性：其中一个命令失败，其他命令依旧执行，没有回滚的概念。</li>
</ul>
<h3 id="五个命令："><a href="#五个命令：" class="headerlink" title="五个命令："></a>五个命令：</h3><p>Multi  标记事务的开始：输入的命令会依次进入命令队列，但不会执行</p>
<p>exec 执行事务 ：执行命令队列</p>
<p>discard 清空事务命令：放弃组队</p>
<pre><code class="linux">#    开启事务
127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; set k1 v1
QUEUED
127.0.0.1:6379(TX)&gt; set k2 v2
QUEUED
#    执行事务
127.0.0.1:6379(TX)&gt; exec
1) OK
2) OK
#    开启事务
127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; set k3 v3
QUEUED
127.0.0.1:6379(TX)&gt; set k4 v4
QUEUED
#    放弃事务
127.0.0.1:6379(TX)&gt; discard
OK
127.0.0.1:6379&gt;</code></pre>
<p>若multi组队过程中有错误命令，则全部命令都不会执行：</p>
<pre><code class="linux">127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; set k1 v1
QUEUED
127.0.0.1:6379(TX)&gt; set k2 v2
QUEUED
#    命令错误
127.0.0.1:6379(TX)&gt; set k3
(error) ERR wrong number of arguments for &#39;set&#39; command
#    不会执行，直接放弃事务
127.0.0.1:6379(TX)&gt; exec
(error) EXECABORT Transaction discarded because of previous errors.</code></pre>
<p>若执行过程中有不能执行的命令，不会影响其他命令的执行</p>
<pre><code class="linux">127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; set k1 v1
QUEUED
127.0.0.1:6379(TX)&gt; set k2 v2
QUEUED
# 此命令不能正确执行 ， v1不能增量
127.0.0.1:6379(TX)&gt; incr k1
QUEUED
127.0.0.1:6379(TX)&gt; exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range</code></pre>
<p>watch和unwatch在下面说明</p>
<h3 id="事务与锁"><a href="#事务与锁" class="headerlink" title="事务与锁"></a>事务与锁</h3><p>悲观锁：每次拿数据都认为数据会被别人修改，所以每次操作都上锁。</p>
<p>乐观锁：就是每次拿数据都认为数据不会被别人修改，所以不上锁，但是在每次更新的时候会判断一下数据有没有被别人修改，可以使用版本号标记。乐观锁适用于多读的场景，可以提高吞吐量。</p>
<p>Redis就是利用乐观锁的check-and-set机制实现事务的。</p>
<p>watch命令</p>
<p>​    监视一个(或多个) key ，如果在事务执行之前这个(或这些) key 被其他命令所改动，那么事务将被打断。</p>
<p>unwatch命令取消 WATCH 命令对所有 key 的监视。</p>
<pre><code class="linux">#客户端1
127.0.0.1:6379&gt; get k1
&quot;10&quot;
127.0.0.1:6379&gt; watch k1
OK
127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; incr k1
QUEUED
127.0.0.1:6379(TX)&gt; exec
1) (integer) 11</code></pre>
<pre><code class="linux">#客户端2
127.0.0.1:6379&gt; watch k1
OK
127.0.0.1:6379&gt; multi
OK
127.0.0.1:6379(TX)&gt; incr k1
QUEUED
# k1被客户端1修改了 事务执行失败
127.0.0.1:6379(TX)&gt; exec
(nil)</code></pre>
<h2 id="持久化"><a href="#持久化" class="headerlink" title="持久化"></a>持久化</h2><p>​    Redis的数据存储在内存里，一但重启数据则丢失。因此Redis有提供持久化的机制将数据写到磁盘中，以备份和还原数据。</p>
<p>两种方式PDB和AOF。</p>
<h3 id="PDB"><a href="#PDB" class="headerlink" title="PDB"></a>PDB</h3><p>RDB，即Redis Database，以指定的时间间隔把数据以快照的形式保存在磁盘上。</p>
<p>​    在某个时间点将数据写入一个临时文件，持久化结束后，用这个临时文件替换 上次持久化的文件，达到数据恢复。</p>
<p>优点：  </p>
<p>1.只有一个文件 dump.rdb，全量备份，非常适合用于进行备份和灾难恢复。</p>
<p>2.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。</p>
<p>3.性能最大化，fork 子进程来完成写操作，让主进程继续处理命令。(使用单独子进程来进行持久化，主进程不会进行任何 IO 操作，保证了 redis 的高性能) </p>
<p>缺点：  </p>
<p>数据安全性低。(RDB 是间隔一段时间进行持久化，如果持久化之间 redis 发生故障，会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)</p>
<p>最后一次持久化操作可能丢失。</p>
<h3 id="AOF"><a href="#AOF" class="headerlink" title="AOF"></a>AOF</h3><p>AOF，即append only file，是以追加的方式把redis操作日志写入到磁盘上。AOF的主要作用是解决了数据持久化的实时性，目前已经是Redis持久化的主流方式</p>
<p>优点： </p>
<p>1.数据安全，Redis中提供了3种同步策略，即每秒同步、每次修改同步和不同步。默认每秒同步，如出现故障只丢失1秒数据。</p>
<p> 2.如果日志过大，Redis可以自动启用rewrite机制对文件就行优化压缩。</p>
<p>缺点：  </p>
<p>1.AOF 文件比 RDB 文件大，且恢复速度慢。  </p>
<p>2.数据集大的时候，比 rdb 启动效率低。</p>
<h2 id="主从复制"><a href="#主从复制" class="headerlink" title="主从复制"></a>主从复制</h2><p>主服务器:master </p>
<p>从服务器:slave</p>
<p>一个master可以拥有多个slave，一个slave只能对应一个master</p>
<p>主从复制即将master中的数据即时，有效的同步到slave中。</p>
<p>特点:</p>
<ul>
<li>master<ul>
<li>写数据</li>
<li>将写的数据同步到slave中</li>
</ul>
</li>
<li>slave<ul>
<li>读数据</li>
</ul>
</li>
</ul>
<h3 id="作用"><a href="#作用" class="headerlink" title="作用:"></a>作用:</h3><ul>
<li>读写分离：master负责写，slave负责读，提高服务器读写负载。</li>
<li>负载均衡：基于主从结构，配合读写分离，由slave分担master负载，并根据需求的变化改变slave的数量，通过多个节点分担数据读取负载，提高Redis服务器并发量和吞吐量。</li>
<li>故障恢复：当master出现故障时，由slave提供服务，实现快速的故障恢复。</li>
<li>数据冗余：实现数据热备份，作为持久化之外的一种数据冗余。</li>
<li>高可用基石：基于主从复制，构建哨兵模式与集群，实现Redis的高可用方案</li>
</ul>
<h3 id="三个阶段"><a href="#三个阶段" class="headerlink" title="三个阶段"></a>三个阶段</h3><p>主从复制大体可以分为3个阶段</p>
<ul>
<li>建立连接</li>
<li>数据同步</li>
<li>命令传播</li>
</ul>
<h4 id="建立连接"><a href="#建立连接" class="headerlink" title="建立连接"></a>建立连接</h4><ol>
<li>设置master的地址和端口，保存master信息</li>
<li>建立socket连接</li>
<li>发送ping命令(计时器任务)</li>
<li>身份验证</li>
<li>发送slave信息</li>
</ol>
<p>具体如图:</p>
<p><img src="(https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/conn.png)" alt="conn"></p>
<p>图来源:<a href="https://www.bilibili.com/video/BV1XV411o7xP?p=85" target="_blank" rel="noopener">Redis教程，入门到实战</a></p>
<p>连接方式：</p>
<pre><code class="linux">#方式一：客户端发送命令
slaveof   masterip   masterport

#方式二：启动从服务器的时直接连接
redis-server   -slaveof   masterip  masterport 

#方式三：从服务器的配置文件配置（这种情况使用多）
slaveof  masterip  masterport</code></pre>
<h4 id="数据同步"><a href="#数据同步" class="headerlink" title="数据同步"></a>数据同步</h4><ol>
<li>请求同步数据</li>
<li>创建PDB同步数据 (获取发送同步指令之前的数据)</li>
<li>恢复PDB同步数据 </li>
<li>请求部分同步数据 (获取PDB同步过程中新的数据)</li>
<li>恢复部分同步数据</li>
</ol>
<p>具体如下:</p>
<p><img src="(https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/sync.png)" alt="conn"></p>
<p>图来源:<a href="https://www.bilibili.com/video/BV1XV411o7xP?p=87" target="_blank" rel="noopener">Redis教程，入门到实战</a></p>
<h4 id="命令传播"><a href="#命令传播" class="headerlink" title="命令传播"></a>命令传播</h4><p>​    runid，复制缓冲区，偏移量offset，心跳机制。。。</p>
<p><img src="(https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/2.png)" alt="2"></p>
<h2 id="哨兵"><a href="#哨兵" class="headerlink" title="哨兵"></a>哨兵</h2><p>​    哨兵(sentinel)是一个分布式系统，用于对主从结构中的每台服务器进行监控，当出现故障时通过投票机制选择新的master并将所有slave连接到新的master。</p>
<h3 id="作用："><a href="#作用：" class="headerlink" title="作用："></a>作用：</h3><ul>
<li><p>监控</p>
<ul>
<li>不断检查master和slave是否正常运行</li>
<li>master存活检查，master和slave运行情况检查</li>
</ul>
</li>
<li><p>通知</p>
<ul>
<li>当被监控的服务器出现问题时，向其他服务器发送通知</li>
</ul>
</li>
<li><p>自动故障转移</p>
<ul>
<li>断开master和slave连接，选取一个slave作为master，将其他slave连接到新的master，并告知客户端新的服务器地址。</li>
</ul>
<p>哨兵也是一台Redis服务器，只是不提供服务。</p>
<p>通常哨兵配置数量为单数。</p>
</li>
</ul>
<h3 id="监控阶段"><a href="#监控阶段" class="headerlink" title="监控阶段"></a>监控阶段</h3><ul>
<li>哨兵与master建立cmd连接</li>
<li>哨兵之间通过发布与订阅建立网络，同步信息</li>
<li>同步各个节点的状态信息<ul>
<li>获取各个sentinel的状态，ping命令</li>
<li>获取master的状态，info命令<ul>
<li>master的属性: runid，role(master)</li>
<li>各个slave的详细信息</li>
</ul>
</li>
<li>获取各个slave的状态，info命令<ul>
<li>slave属性: runid，role，offset等</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="(https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/sentinel.png)" alt="sentinel"></p>
<h3 id="通知阶段"><a href="#通知阶段" class="headerlink" title="通知阶段"></a>通知阶段</h3><p>​    通知阶段是一个维持长期通信的阶段</p>
<p><img src="(https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/Redis/advice.png)" alt="advice"></p>
<h3 id="故障转移"><a href="#故障转移" class="headerlink" title="故障转移"></a>故障转移</h3><p>发现问题-&gt;竞选负责人-&gt;挑选新master-&gt;切换新的master</p>
<ul>
<li><p>主观下线：当有sentinel认为master下线</p>
</li>
<li><p>客观下线：当超过一定的sentinel认为master下线(通常配置为半数+1)</p>
</li>
<li><p>当master客观下线时，sentinel之间会选举出一台sentinel进行故障处理。</p>
</li>
<li><p>服务器列表中挑选出备选master</p>
<ul>
<li>在线的</li>
<li>响应快的</li>
<li>与master断开时间短的</li>
<li>优选原则<ul>
<li>优先级</li>
<li>offset</li>
<li>runid</li>
</ul>
</li>
</ul>
</li>
<li><p>发送指令</p>
<ul>
<li>向新的master发送slaveof no one</li>
<li>向其他slave发送slaveof 新ip端口</li>
</ul>
</li>
</ul>
<h2 id="集群"><a href="#集群" class="headerlink" title="集群"></a>集群</h2><p>​    集群简单来说就是使用网络将若干台计算机联通起来，并提供统一的管理方式，对外呈现出单机服务的效果。</p>
<p>作用：</p>
<ul>
<li>分散单台服务器的访问压力，实现负载均衡</li>
<li>分散单台服务器的存储压力，实现可扩展性</li>
<li>降低单台服务器宕机带来的业务灾难</li>
</ul>
<h2 id="Redis运行时的一些问题"><a href="#Redis运行时的一些问题" class="headerlink" title="Redis运行时的一些问题"></a>Redis运行时的一些问题</h2><h3 id="缓存穿透"><a href="#缓存穿透" class="headerlink" title="缓存穿透"></a>缓存穿透</h3><p>​    缓存穿透是指缓存和数据库中都没有的数据，而用户不断发起请求，如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者，攻击会导致数据库压力过大。</p>
<p>​    此时，缓存起不到作用，请求每次都会走到数据库，流量大时数据库可能会被打挂。此时缓存就好像被“穿透”了一样，起不到任何作用。</p>
<p>​    解决方案：</p>
<ol>
<li><strong>接口校验</strong>。接口层增加校验，如用户鉴权校验，id做基础校验，id&lt;=0的直接拦截；</li>
<li><strong>缓存空值</strong>。从缓存取不到的数据，在数据库中也没有取到，这时也可以将key-value对写为key-null，缓存有效时间可以设置短点，如30秒（设置太长会导致正常情况也没法使用）。这样可以防止攻击用户反复用同一个id暴力攻击；</li>
<li><strong>布隆过滤器</strong>。使用布隆过滤器存储所有可能访问的 key，不存在的 key 直接被过滤，存在的 key 则再进一步查询缓存和数据库。</li>
</ol>
<h3 id="缓存击穿"><a href="#缓存击穿" class="headerlink" title="缓存击穿"></a>缓存击穿</h3><p>​    同时有大量重复的请求打进来，由于此时缓存的某个key不存在(过期，失效，或者压根就没有，反正就是redis里现在没有这key)，所以请求最终都会走到数据库，造成瞬时数据库请求量大、压力骤增，甚至可能打垮数据库。</p>
<p>解决方案：</p>
<ol>
<li><strong>热点数据不过期</strong>。直接将缓存设置为不过期，然后由定时任务去异步加载数据，更新缓存。这种方式适用于比较极端的场景，例如流量特别特别大的场景，使用时需要考虑业务能接受数据不一致的时间，还有就是异常情况的处理，不要到时候缓存刷新不上，一直是脏数据，那就凉了。</li>
<li><strong>加互斥锁</strong>。在并发的多个请求中，只有第一个请求线程能拿到锁并执行数据库查询操作，其他的线程拿不到锁就阻塞等着，等到第一个线程将数据写入缓存后，直接走缓存。</li>
</ol>
<h3 id="缓存雪崩"><a href="#缓存雪崩" class="headerlink" title="缓存雪崩"></a>缓存雪崩</h3><p>​    同时有大量的请求打进来，由于此时缓存的key不存在(多个key过期，失效，或者压根就没有，反正就是redis里现在没有这key)，造成瞬时数据库请求量大、压力骤增，引起雪崩，甚至导致数据库被打挂。</p>
<p>缓存雪崩其实有点像“升级版的缓存击穿”，缓存击穿是一个热点 key，缓存雪崩是一组热点 key。</p>
<p>解决方案：</p>
<ol>
<li><strong>过期时间打散</strong>。既然是大量缓存集中失效，那最容易想到就是让他们不集中生效。可以给缓存的过期时间时加上一个随机值时间，使得每个 key 的过期时间分布开来，不会集中在同一时刻失效。</li>
<li><strong>热点数据不过期</strong>。该方式和缓存击穿一样，也是要着重考虑刷新的时间间隔和数据异常如何处理的情况。</li>
<li><strong>加互斥锁</strong>。该方式和缓存击穿一样，按 key 维度加锁，对于同一个 key，只允许一个线程去计算，其他线程原地阻塞等待第一个线程的计算结果，然后直接走缓存即可。</li>
</ol>
<h3 id="删除策略（缓存失效策略、数据过期策略"><a href="#删除策略（缓存失效策略、数据过期策略" class="headerlink" title="删除策略（缓存失效策略、数据过期策略"></a>删除策略（缓存失效策略、数据过期策略</h3><p>定时删除：在设置键的过期时间的同时，创建一个定时器，让定时器在键的过期时间来临时，立即执行对键的删除操作。对内存最友好，对 CPU 时间最不友好。</p>
<p>惰性删除：放任键过期不管，但是每次获取键时，都检査键是否过期，如果过期的话，就删除该键；如果没有过期，就返回该键。对 CPU 时间最优化，对内存最不友好。</p>
<p>定期删除：每隔一段时间，默认100ms，程序就对数据库进行一次检査，删除里面的过期键。至于要删除多少过期键，以及要检査多少个数据库，则由算法决定。前两种策略的折中，对 CPU 时间和内存的友好程度较平衡。</p>
<p>Redis 使用惰性删除和定期删除。</p>

        </div>
        <!-- .entry-content -->
        
        <p></p>
          
        <div style="text-align:center; width: 100%" class="social-share share-mobile" data-disabled="diandian, tencent"></div>
        <footer class="post-footer">
          <div class="post-lincenses"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="nofollow"><i class="fa fa-creative-commons" aria-hidden="true"></i> 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a></div>
          <div class="post-tags">
            <div class="tag-cloud">
              <div class="tag-cloud-title">
              </div>
              <div class="tag-cloud-tags">
              <a href="/tags/CDN/" style="font-size: 10px; color: #f38181">CDN</a> <a href="/tags/Chrome/" style="font-size: 10px; color: #f38181">Chrome</a> <a href="/tags/Collection/" style="font-size: 10px; color: #f38181">Collection</a> <a href="/tags/ElasticSearch/" style="font-size: 10px; color: #f38181">ElasticSearch</a> <a href="/tags/IO%E6%B5%81/" style="font-size: 10px; color: #f38181">IO流</a> <a href="/tags/JVM/" style="font-size: 10px; color: #f38181">JVM</a> <a href="/tags/Java/" style="font-size: 16.67px; color: #b4c1b8">Java</a> <a href="/tags/Linux/" style="font-size: 10px; color: #f38181">Linux</a> <a href="/tags/MySQL/" style="font-size: 10px; color: #f38181">MySQL</a> <a href="/tags/OIS/" style="font-size: 10px; color: #f38181">OIS</a> <a href="/tags/Redis/" style="font-size: 13.33px; color: #d4a19c">Redis</a> <a href="/tags/SQL/" style="font-size: 10px; color: #f38181">SQL</a> <a href="/tags/Springboot/" style="font-size: 10px; color: #f38181">Springboot</a> <a href="/tags/TCP-IP/" style="font-size: 10px; color: #f38181">TCP/IP</a> <a href="/tags/Tomcat/" style="font-size: 10px; color: #f38181">Tomcat</a> <a href="/tags/aop/" style="font-size: 10px; color: #f38181">aop</a> <a href="/tags/bili/" style="font-size: 10px; color: #f38181">bili</a> <a href="/tags/eclipse/" style="font-size: 10px; color: #f38181">eclipse</a> <a href="/tags/git/" style="font-size: 10px; color: #f38181">git</a> <a href="/tags/github/" style="font-size: 13.33px; color: #d4a19c">github</a> <a href="/tags/ioc/" style="font-size: 10px; color: #f38181">ioc</a> <a href="/tags/java/" style="font-size: 20px; color: #95e1d3">java</a> <a href="/tags/jsdelivr/" style="font-size: 10px; color: #f38181">jsdelivr</a> <a href="/tags/oracle/" style="font-size: 10px; color: #f38181">oracle</a> <a href="/tags/spring/" style="font-size: 13.33px; color: #d4a19c">spring</a> <a href="/tags/sring/" style="font-size: 10px; color: #f38181">sring</a> <a href="/tags/vscode/" style="font-size: 10px; color: #f38181">vscode</a> <a href="/tags/web/" style="font-size: 10px; color: #f38181">web</a> <a href="/tags/%E5%8F%8D%E5%B0%84/" style="font-size: 10px; color: #f38181">反射</a> <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" style="font-size: 10px; color: #f38181">多线程</a> <a href="/tags/%E5%AE%9E%E4%B9%A0/" style="font-size: 10px; color: #f38181">实习</a> <a href="/tags/%E6%8E%92%E5%BA%8F/" style="font-size: 10px; color: #f38181">排序</a> <a href="/tags/%E6%B3%A8%E8%A7%A3/" style="font-size: 10px; color: #f38181">注解</a> <a href="/tags/%E6%B4%BE%E5%A4%A7%E6%98%9F/" style="font-size: 10px; color: #f38181">派大星</a> <a href="/tags/%E7%BD%91%E7%BB%9C/" style="font-size: 10px; color: #f38181">网络</a>
              </div>
            </div>
          </div>
          <div class="post-share">
            <div class="social-share sharehidden share-component"></div>
            <i class="iconfont show-share icon-forward"></i>
          </div>
        </footer><!-- .entry-footer -->
      </article>
      <!-- #post-## -->
      <div class="toc" style="background: none;"></div>
      <section class="post-squares nextprev">
        
          
            <div class="post-nepre half previous">
          
            <a href="/posts/6a343b7f.html" rel="prev">
              <div class="background">
<!--                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-q2lm9l.jpg" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-q2lm9l.jpg">-->
                
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-q2lm9l.jpg" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" >
              </div>
              <span class="label">
              Previous Post</span>
              <div class="info">
                <h3>
                Redis入门</h3>
                <hr>
              </div>
            </a>
          </div>
        
        
          
            <div class="post-nepre half next">
          
            <a href="/posts/62d904b9.html" rel="next">
              <div class="background">
                
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-9mr9zw.png" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" >
              </div>
              <span class="label">
              Next Post</span>
              <div class="info">
                <h3>
                Spring框架</h3>
                <hr>
              </div>
            </a>
          </div>
        
      </section>
      
      <section class="author-profile">
        <div class="info" itemprop="author" itemscope="" itemtype="https://schema.org/Person">
          <a href="" class="profile gravatar"><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg" itemprop="image" alt="Conor_hua" height="70" width="70"></a>
          <div class="meta">
            <span class="title">Author</span>
            <h3 itemprop="name">
            <a href="" itemprop="url" rel="author">Conor_hua</a>
            </h3>
          </div>
        </div>
        <hr>
        <p><i class="iconfont icon-write"></i></p>
      </section>
    </main><!-- #main -->
  </div><!-- #primary -->
</div>


    </div>    
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="请输入关键词..."/>
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            // PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
    <!-- <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 Conor_hua<br>
      powered_by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer> -->
<footer id="colophon" class="site-footer" role="contentinfo">
    <div class="site-info">
        <div class="footertext">
            <div class="img-preload">
                <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/wordpress-rotating-ball-o.svg">
                <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/disqus-preloader.svg">
            </div>
            
            <p>本站总访问量：<a id="allcount"></a></p>
            <p style="color: #666666;">it you can dream it you can do it</p>
            
                <p id="momk" style="font-family: 'Ubuntu', sans-serif;color: #b9b9b9;"></p>
            
        </div>
        <div class="footer-device">
            <p style="font-family: 'Ubuntu', sans-serif;">
 <span style=""> <a 
                         style="color: 	#FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);">Conor_hua</a> <i
             class="iconfont icon-sakura rotating" style="color: #ffc0cb;display:inline-block"></i> Theme <a
             href="https://github.com/xbclub/Hexo-theme-sakura" target="_blank"
             style="color: #FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);">Sakura</a><a
             
             style="color: #b9b9b9;;text-decoration: underline dotted rgba(0, 0, 0, .1);">, Powered by</a><a
             href="https://github.com/hexojs/hexo" target="_blank"
             style="color: #FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);"> Hexo</a>
        </span>
            </p>
        </div>
    </div><!-- .site-info -->
    <!--壁纸切换-->
  <div class="skin-menu no-select" id="mainskin"  style="position: fixed">
    <div class="theme-controls row-container">
        <ul class="menu-list">
            <li id="white-bg"> <i class="fa fa-television" aria-hidden="true"></i></li>
            <li id="sakura-bg"> <i class="iconfont icon-sakura"></i></li>
            <li id="gribs-bg"> <i class="fa fa-slack" aria-hidden="true"></i></li>
            <li id="KAdots-bg"> <i class="iconfont icon-dots"></i></li>
            <li id="totem-bg"> <i class="fa fa-optin-monster" aria-hidden="true"></i></li>
            <li id="pixiv-bg"> <i class="iconfont icon-pixiv"></i></li>
            <li id="bing-bg"> <i class="iconfont icon-bing"></i></li>
            <li id="dark-bg"> <i class="fa fa-moon-o" aria-hidden="true"></i></li>
        </ul>
    </div>
    <div class="font-family-controls row-container">
        <button type="button" class="control-btn-serif selected" data-mode="serif" onclick="mashiro_global.font_control.change_font()">Serif</button>
        <button type="button" class="control-btn-sans-serif" data-mode="sans-serif" onclick="mashiro_global.font_control.change_font()">Sans Serif</button>
    </div>
</div>   
<canvas id="night-mode-cover"></canvas> 
  <div class="changeSkin-gear no-select">
    <div class="keys" id="setbtn"> <span id="open-skinMenu"> 切换壁纸 | SCHEME TOOL 
      &nbsp;<i class="iconfont icon-gear inline-block rotating"></i> </span></div>
</div><!--skin.end-->
</footer>


<!--<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.7/js/tocbot.min.js"></script>-->

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/lib.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/InsightSearch.js"></script>
<script type="text/javascript"
        src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/jquery.fancybox.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/zoom.min.js"></script>

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@1.2/js/sakura-app.js"></script>
    
<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/av-min.js"></script>
<script src='https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/Valine.min.js'></script>
<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/botui.js"></script>
<!-- 不蒜子 网页计数器 -->

      
       <script>
  fetch('https://counts.42cloud.cn/api/counts.html')
        .then(response => response.json())
        .then(data => {
              if (document.getElementById("readcount")) {
                document.getElementById("readcount").innerHTML=data.Count;
            }
            if (document.getElementById("allcount")){
                document.getElementById("allcount").innerHTML=data.Allcount;
            }
        })
        .catch(err => console.error(err))
</script>
      
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script> -->
<script type="text/javascript">
    /* <![CDATA[ */
    if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
        var Poi = {
            "pjax": "1",
            "movies": {"url": "https://cdn.jsdelivr.net/gh/honjun/hojun@1.2", "name": "Unbroken.mp4", "live": "close"},
            "windowheight": "fixed",
            "codelamp": "close",
            "ajaxurl": "",
            "order": "asc",
            "formpostion": "bottom"
        };
    } else {
        var Poi = {
            "pjax": "1",
            "movies": {"url": "https://cdn.jsdelivr.net/gh/honjun/hojun@1.2", "name": "Unbroken.mp4", "live": "open"},
            "windowheight": "auto",
            "codelamp": "close",
            "ajaxurl": "",
            "order": "asc",
            "formpostion": "bottom"
        };
    }
    /* ]]> */

</script>
<script>
    $(document).ready(function () {
        if ($(".toc").length > 0 && document.body.clientWidth > 1200) {
            if ($(".pattern-center").length > 0) { //有图的情况
                tocbot.init({
                    // Where to render the table of contents.
                    tocSelector: '.toc', // 放置目录的容器
                    // Where to grab the headings to build the table of contents.
                    contentSelector: '.entry-content', // 正文内容所在
                    // Which headings to grab inside of the contentSelector element.
                    scrollSmooth: true,
                    headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
                    headingsOffset: -400,
                    scrollSmoothOffset: -85
                });
            } else {
                tocbot.init({
                    // Where to render the table of contents.
                    tocSelector: '.toc', // 放置目录的容器
                    // Where to grab the headings to build the table of contents.
                    contentSelector: '.entry-content', // 正文内容所在
                    // Which headings to grab inside of the contentSelector element.
                    scrollSmooth: true,
                    headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
                    headingsOffset: -85,
                    scrollSmoothOffset: -85
                });
            }
            var offsetTop = $('.toc').offset().top - 95;
            window.onscroll = function () {
                var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
                if (scrollTop >= offsetTop) {
                    $('.toc').addClass('toc-fixed');
                } else {
                    $('.toc').removeClass('toc-fixed');
                }
            }
        }
    });

</script>
<span style="color: #FF69B4 ;padding-left: 20px;">
    <i class="fa fa-clock-o" aria-hidden="true"></i>
    <span id="time" align="center">载入时间中...</span>

    <script type="text/javascript">
        function NewDate(str) {
            str = str.split('-');
            var date = new Date();
            date.setUTCFullYear(str[0], str[1] - 1, str[2]);
            date.setUTCHours(0, 0, 0, 0);
            return date;
        }

        function momxc() {
            var birthDay = NewDate("2020-7-16");
            var today = new Date();
            var timeold = today.getTime() - birthDay.getTime();
            var sectimeold = timeold / 1000
            var secondsold = Math.floor(sectimeold);
            var msPerDay = 24 * 60 * 60 * 1000;
            var e_daysold = timeold / msPerDay;
            var daysold = Math.floor(e_daysold);
            var e_hrsold = (daysold - e_daysold) * -24;
            var hrsold = Math.floor(e_hrsold);
            var e_minsold = (hrsold - e_hrsold) * -60;
            var minsold = Math.floor((hrsold - e_hrsold) * -60);
            var seconds = Math.floor((minsold - e_minsold) * -60).toString();
            document.getElementById("momk").innerHTML = "本小破站已勉强维持生活" + daysold + "天" + hrsold + "小时" + minsold + "分" + seconds + "秒";
            setTimeout(momxc, 1000);
        }
        
        momxc();
    </script>


</span>


    <div class="openNav no-select" style="height: 50px;">
      <div class="iconflat no-select" style="width: 50px; height: 50px;">
        <div class="icon"></div>
      </div>
      <div class="site-branding search-form-submit">
        <i class="iconfont js-toggle-search iconsearch icon-search"></i>
      </div>
    </div>
  </section>
  <div id="mo-nav" class="">
  <div class="m-avatar">
    <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
  </div>
  <p style="text-align: center; color: #333; font-weight: 900; font-family: 'Ubuntu', sans-serif; letter-spacing: 1.5px">Conor_hua</p>
  <p style="text-align: center; word-spacing: 20px;">
    
  </p>
  <ul id="menu-new-1" class="menu">
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
            首页
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
            归档
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/%E6%8A%80%E6%9C%AF/">
                  <i class="fa fa-code" aria-hidden="true"></i>
                  技术
                </a>
              </li>
            
              <li>
                <a href="/categories/%E5%B9%B2%E8%B4%A7/">
                  <i class="fa fa-plug" aria-hidden="true"></i>
                  干货
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="javascript:;">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
            清单
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/bangumis/">
                  <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                  番剧
                </a>
              </li>
            
              <li>
                <a href="/categories/%E6%94%B6%E8%97%8F/">
                  <i class="fa fa-star" aria-hidden="true"></i>
                  收藏
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/tags/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-tags" aria-hidden="true"></i>
            标签
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="javascript:;">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
            关于
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/about/">
                  <i class="fa fa-meetup" aria-hidden="true"></i>
                  我？
                </a>
              </li>
            
              <li>
                <a href="/theme-sakura/">
                  <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                  主题
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/links/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
            友人帐
          </span>
        </a>
        
      </li>
    
  </ul>
  <p style="text-align: center; font-size: 13px; color: #b9b9b9;">&copy 2019 hexo-sakura</p>
</div>
<button onclick="topFunction()" class="mobile-cd-top" id="moblieGoTop" title="Go to top" style="display: none;"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
  
</body>
<script src="https://cdn.jsdelivr.net/gh/conorhua/asset/js/noSomeKey.js"></script>
</html>